#include<string>
#include<vector>
#include<array>
#include<unordered_map>
#include<algorithm>
#include<limits>
#include <stack>
#include<iostream>
#include<sstream>
#include<deque>
#define MOD 1000000007
class UnionFind {
private:
     // 存储每个元素的父节点
    std::vector<int> rank;    // 存储每个集合的秩（用于按秩合并）
    int count;                // 元素的总数量

public:
    std::vector<int> parent;
    // 构造函数，初始化并查集
    UnionFind(int size) : count(size) {
        parent.resize(size);
        rank.resize(size, 0);
        
        // 初始化每个元素的父节点为自身
        for (int i = 0; i < size; ++i) {
            parent[i] = i;
        }
    }
    
    // 查找元素的根节点，使用路径压缩优化
    int find(int& x) {
        // 如果x不是根节点，递归查找其父节点的根节点，并将x直接连接到根节点（路径压缩）
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
    
    // 合并两个元素所在的集合，使用按秩合并优化
    void unite(int &x, int& y, std::array<bool,100001> &tr) {
        // 查找两个元素的根节点
        int rootX = find(x);
        int rootY = find(y);
        
        // 如果已经在同一个集合中，则不需要合并
        if (rootX == rootY) {
            return;
        }
        
        // 按秩合并：将秩较小的树合并到秩较大的树的根节点下
        if (rank[rootX] < rank[rootY]) {
            parent[rootX] = rootY;
            if (tr[rootX])
            {
                tr[rootY] = true;
            }
        } else {
            parent[rootY] = rootX;
            // 如果秩相等，合并后秩加1
            if (rank[rootX] == rank[rootY]) {
                rank[rootX]++;
            }
            if (tr[rootY])
            {
                tr[rootX] = true;
            }
        }
       
    }
    
    // 判断两个元素是否在同一个集合中
    bool isConnected(int x, int y) {
        return find(x) == find(y);
    }
    
    // 获取当前集合的数量
    int getCount() const {
        return count;
    }
};
bool compar(std::vector<int>& a, std::vector<int>& b)
{
    return a[2] < b[2];
}
class Solution {
public:
  
    std::vector<int> findAllPeople(int n, std::vector<std::vector<int>>& meetings, int firstPerson) {
        std::array<bool,100001> tr;
        tr.fill(false);
        tr[0] = true;
        tr[firstPerson] = true;
        UnionFind unionFind(n);
        std::sort(meetings.begin(), meetings.end(), compar);
        int len = meetings.size();
        for (int i = 0,r=0; i < len ; )
        {
            r= i;
            while (r+1 <len &&meetings[r][2]==meetings[r+1][2])
            {
                r++;
            }
            for (int j=i;j<=r;j++)
            {
                unionFind.unite(meetings[j][0],meetings[j][1],tr);
            }
            for (int j =i,a=0,b=0;j<=r;j++)
            {
                 a=meetings[j][0];
                 b =meetings[j][1];
                if (!tr[unionFind.find(a)])
                {
                    unionFind.parent[a] = a;
                }
                if (!tr[unionFind.find(b)])
                {
                    unionFind.parent[b] = b;
                }
            }
            i=r+1;
        }
        std::vector<int> res;
        for (int i=0;i<n;i++)
        {
            if (tr[unionFind.find(i)])
                res.push_back(i);
        }
        return res;
    }
   
};
